package de.lazy.concurrent;

import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * 
 * General thread utilities class.
 * @author rrath
 *
 */
public class ThreadUtilities {

	/** private constructor to prevent single object creation,
	 * this class only contains statics */
	private ThreadUtilities(){
	}
	
	/** Task queue that gets processed by the {@link #taskWorker}*/
	private static ConcurrentLinkedQueue<Runnable> taskQueue;
	
	/** Worker thread that consecutively executes the {@link Runnable#run()} method
	 * from the entries in {@link #taskQueue} */
	private static Thread taskWorker;

	/** run flag of the {@link #taskWorker} */
	private static boolean running;
	
	/** 
	 * Causes task.run() to be executed asynchronously from the calling thread. <br><br>
	 * 
	 * The Runnable will be added to the local {@link #taskQueue} and will be 
	 * executed by the {@link #taskWorker} thread. 
	 *  
	 * @param task Asynchronous task
	 */
	public static void invokeTask(Runnable task){
		if(taskQueue == null){
			taskQueue = new ConcurrentLinkedQueue<Runnable>();
		}
		
		if(!running){
			start();
		}
		
		taskQueue.add(task);
		
		synchronized (taskWorker) {
			taskWorker.notifyAll();
		}
		
	}

	/** starts the local worker thread */
	private static void start() {
		if(!running || taskWorker == null){
			
			running = true;
			
			//TODO:extract runnable
			taskWorker = new Thread(new Runnable() {
				
				@Override
				public void run() {
					while(running){
						
						//wait for incoming tasks
						if(taskQueue.isEmpty()){
							try {
								synchronized (taskWorker) {
									taskWorker.wait();
								}
								
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
						else{
							Runnable task = taskQueue.poll();
							task.run();
							
						}
					}
					
				}
			});
			taskWorker.setName("ThreadHelper-TaskQueue-"+taskWorker.getId());
			taskWorker.start();
		}
	}


	
	
}
